﻿#region Usings

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;

#endregion

namespace XPressify.Core.Unity
{
    public class UnityControllerFactory : DefaultControllerFactory
    {
        private readonly IUnityContainer _container;

        #region UnityControllerFactory

        public UnityControllerFactory(IUnityContainer container)
        {
            _container = container;
        }

        #endregion

        #region GetControllerInstance

        /// <summary>
        ///   Gets the controller instance.
        /// </summary>
        /// <param name = "reqContext">The req context.</param>
        /// <param name = "controllerType">Type of the controller.</param>
        /// <returns></returns>
        protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType)
        {
            IController controller;
            if (controllerType == null)
            {
                throw new HttpException(
                    404,
                    String.Format(
                        "The controller for path '{0}' could not be found or it does not implement IController.",
                        reqContext.HttpContext.Request.Path)
                    );
            }

            if (!typeof(IController).IsAssignableFrom(controllerType))
                throw new ArgumentException(
                    String.Format("Type requested is not a controller: {0}", controllerType.Name), "controllerType");

            try
            {
                controller = _container.Resolve(controllerType) as IController;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(
                    String.Format("Error resolving controller {0}", controllerType.Name), ex);
            }

            return controller;
        }

        #endregion

        #region MvcUnityContainer

        public static class MvcUnityContainer
        {
            public static UnityContainer Container { get; set; }
        }

        #endregion

        #region CreateController

        /// <summary>
        ///   Injects a custom attribute 
        ///   on every action that is invoked by the controller
        /// </summary>
        /// <param name = "requestContext">The request context</param>
        /// <param name = "controllerName">The name of the controller</param>
        /// <returns>An instance of a controller</returns>
        public override IController CreateController(RequestContext requestContext, string controllerName)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }

            if (String.IsNullOrEmpty(controllerName))
                throw new ArgumentException("Value cannot be null or empty.", "controllerName");

            var controllerType = GetControllerType(requestContext, controllerName);
            var controller = GetControllerInstance(requestContext, controllerType);

            return controller;
        }

        #endregion
    }
}